/**
 * Copyright (C),2011-2012,北京国电通网络技术有限公司.
 * FileName:	upLoop.cpp
 * Author:		LiuHaifeng
 * Version:		V0.1
 * Date:		2011-11-15
 * Description	This file receives data from serial, and put them in list by some fixed format, in order to dispose
 */

/**
 * History:
 * 		Author		date		Version		Description
 *  LiuHaifeng  2012-03-10	  	V1.0.5     add light and curtain socketID validate
 */

#include "upLoop.h"
#include "../sqlite/sqlite.h"

extern int optTimes;
extern int optBegin_time;
extern int setLed_ON;
extern int setLed_OFF;

///global variables used in this file
#if defined SMARTHOME_DEBUG
#ifdef DEBUG_PC
static unsigned char g_buf0[RECVDATA_NUM];					///buffer to receive data from ttyS0.
#elif defined DEBUG_SOCKET
static unsigned char g_buf1[RECVDATA_NUM];
#elif defined DEBUG_ARM
static unsigned char g_buf1[RECVDATA_NUM];
static unsigned char g_buf3[RECVDATA_NUM];
#endif
#elif defined NO_DEBUG_SOCKET
static unsigned char g_buf1[RECVDATA_NUM];					///buffer to receive data from ttyS2.
#elif defined NO_DEBUG_ALL
static unsigned char g_buf1[RECVDATA_NUM];					///buffer to receive data from ttyS2.
static unsigned char g_buf2[RECVDATA_NUM];					///buffer to receive data from ttyS3.
static unsigned char g_buf3[RECVDATA_NUM];					///buffer to receive data from ttyS4.
#endif

static int upLoopInit();
int insertRecv(unsigned char*);
int bcdChange(unsigned char);

extern struct StSerialFD g_serialFD;
extern struct StOther g_other;
extern struct StDataTransmit g_dataTrans;
extern struct StEquipList g_devList;
extern struct StDownTask g_downTask;
extern struct StUpTask g_upTask;
extern struct StRetry g_retry;
extern struct StLED g_LED;
extern unsigned char g_buf2[RECVDATA_NUM];
/***downLoopHandler() brief loop control up-stream dispose
 * param void
 *
 * retval void
 ***/
void upLoopHandler(void)
{
	PRINTOUT("%s","In upLoopHandler()");

	int l_maxfd=0;									///l_maxfd:the max number of file descriptor +1.
	fd_set l_readset;								///read set of file descriptor.

	if(-1==upLoopInit())							///initialize
	{
		ERROROUT("upLoopInit() failed!");
		exit(1);
	}

	///calculate the max file descriptor of "g_serial1/g_serial2/g_serial3"
#if defined SMARTHOME_DEBUG
#ifdef DEBUG_PC
	l_maxfd=g_serialFD.st_serial0;
#elif defined DEBUG_SOCKET
	l_maxfd=g_serialFD.st_serial1;
#elif defined DEBUG_ARM
	l_maxfd=g_serialFD.st_serial1;
	l_maxfd = g_serialFD.st_serial1>g_serialFD.st_serial3?g_serialFD.st_serial1:g_serialFD.st_serial3;
#endif
#elif defined NO_DEBUG_SOCKET
	l_maxfd=g_serialFD.st_serial1;
#elif defined NO_DEBUG_ALL
	l_maxfd=g_serialFD.st_serial1;
	l_maxfd = g_serialFD.st_serial1>g_serialFD.st_serial2?g_serialFD.st_serial1:g_serialFD.st_serial2;
	l_maxfd = l_maxfd >g_serialFD.st_serial3?l_maxfd:g_serialFD.st_serial3;
#endif
	l_maxfd += 1;
	FD_ZERO(&l_readset);							///clear l_readset
#if defined SMARTHOME_DEBUG
#ifdef DEBUG_PC
	FD_SET(g_serialFD.st_serial0,&l_readset);
#elif defined DEBUG_SOCKET
	FD_SET(g_serialFD.st_serial1,&l_readset);
#elif defined DEBUG_ARM
	FD_SET(g_serialFD.st_serial1,&l_readset);
	FD_SET(g_serialFD.st_serial3,&l_readset);
#endif
#elif defined NO_DEBUG_SOCKET
	FD_SET(g_serialFD.st_serial1,&l_readset);
#elif defined NO_DEBUG_ALL
	FD_SET(g_serialFD.st_serial1,&l_readset);		///put "g_serial1/g_serial2/g_serial3" into l_readset
	FD_SET(g_serialFD.st_serial2,&l_readset);
	FD_SET(g_serialFD.st_serial3,&l_readset);
#endif
#if defined SMARTHOME_DEBUG
#ifdef DEBUG_PC
	while(FD_ISSET(g_serialFD.st_serial0, &l_readset))
#elif defined DEBUG_SOCKET
	while(FD_ISSET(g_serialFD.st_serial1, &l_readset))
#elif defined DEBUG_ARM
	while(FD_ISSET(g_serialFD.st_serial1, &l_readset)||FD_ISSET(g_serialFD.st_serial3,&l_readset))
#endif
#elif defined NO_DEBUG_SOCKET
	while(FD_ISSET(g_serialFD.st_serial1, &l_readset))
#elif defined NO_DEBUG_ALL
	while(FD_ISSET(g_serialFD.st_serial1, &l_readset)||FD_ISSET(g_serialFD.st_serial2,&l_readset)||FD_ISSET(g_serialFD.st_serial3,&l_readset))
#endif
	{
		if(select(l_maxfd,&l_readset,NULL,NULL,NULL)<0)
		{
			ERROROUT("no select!");
			///if failed, set them into corresponding set again and continue
			FD_ZERO(&l_readset);
#if defined SMARTHOME_DEBUG
#ifdef DEBUG_PC
			FD_SET(g_serialFD.st_serial0,&l_readset);
#elif defined DEBUG_SOCKET
			FD_SET(g_serialFD.st_serial1,&l_readset);
#elif defined DEBUG_ARM
			FD_SET(g_serialFD.st_serial1,&l_readset);
			FD_SET(g_serialFD.st_serial3,&l_readset);
#endif
#elif defined NO_DEBUG_SOCKET
			FD_SET(g_serialFD.st_serial1,&l_readset);
#elif defined NO_DEBUG_ALL
			FD_SET(g_serialFD.st_serial1,&l_readset);
			FD_SET(g_serialFD.st_serial2,&l_readset);
			FD_SET(g_serialFD.st_serial3,&l_readset);
#endif
			continue;
		}
		else
		{
#if defined SMARTHOME_DEBUG
#ifdef DEBUG_PC
			if(FD_ISSET(g_serialFD.st_serial0,&l_readset))							///debug serial
			{
				PRINTOUT("%s","read from 'g_serial0'--ttyS0(serial5)!");
				myDelay(RECEIVEDELAY);
				memset(g_buf0,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial0,g_buf0,RECVDATA_NUM)==-1)				///read  data from ttyS1
				{
					ERROROUT("read from ttyS0(serial5) failed!");
					tcflush(g_serialFD.st_serial0,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}
				if(-1==insertRecv(g_buf0))											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
#elif defined DEBUG_SOCKET
			if(FD_ISSET(g_serialFD.st_serial1,&l_readset))							///socket
			{
				PRINTOUT("%s","read from 'g_serial1'--ttyS1(serial3)!");
				myDelay(RECEIVEDELAY);
				memset(g_buf1,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial1,g_buf1,RECVDATA_NUM)==-1)				///read  data from ttyS1
				{
					ERROROUT("read from ttyS1(serial3) failed!");
					tcflush(g_serialFD.st_serial1,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}
				if(insertRecv(g_buf1)==-1)											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
#elif defined DEBUG_ARM
			if(FD_ISSET(g_serialFD.st_serial1,&l_readset))							///socket
			{
				PRINTOUT("%s","read from 'g_serial1'--ttyS1(serial3)!");
				myDelay(RECEIVEDELAY);
				memset(g_buf1,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial1,g_buf1,RECVDATA_NUM)==-1)				///read  data from ttyS1
				{
					ERROROUT("read from ttyS1(serial3) failed!");
					tcflush(g_serialFD.st_serial1,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}
				if(insertRecv(g_buf1)==-1)											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
			if(FD_ISSET(g_serialFD.st_serial3,&l_readset))							///Media electrical device
			{
				PRINTOUT("%s","read from 'g_serial3'--ttyS3(serial6)!");
				myDelay(RECEIVEDELAY);
				memset(g_buf3,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial3,g_buf3,RECVDATA_NUM)==-1)				///read  data from ttyS3
				{
					ERROROUT("read from ttyS3(serial6) failed!");
					tcflush(g_serialFD.st_serial3,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}
				if(insertRecv(g_buf3)==-1)											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
#endif
#elif defined NO_DEBUG_SOCKET
			if(FD_ISSET(g_serialFD.st_serial1,&l_readset))							///socket
			{
				PRINTOUT("%s","read from 'g_serial1'--ttyS1(serial3)!");
				myDelay(RECEIVEDELAY);
				memset(g_buf1,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial1,g_buf1,RECVDATA_NUM)==-1)				///read  data from ttyS1
				{
					ERROROUT("read from ttyS1(serial3) failed!");
					tcflush(g_serialFD.st_serial1,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}
				if(insertRecv(g_buf1)==-1)											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
#elif defined NO_DEBUG_ALL
			if(FD_ISSET(g_serialFD.st_serial1,&l_readset))							///socket
			{
				PRINTOUT("%s","read from 'g_serial1'--ttyS1(serial3)!");
				myDelay(RECEIVEDELAY);
				memset(g_buf1,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial1,g_buf1,RECVDATA_NUM)==-1)				///read  data from ttyS1
				{
					ERROROUT("read from ttyS1(serial3) failed!");
					tcflush(g_serialFD.st_serial1,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}
				if(insertRecv(g_buf1)==-1)											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
			if(FD_ISSET(g_serialFD.st_serial2,&l_readset))							///safeguard
			{
				PRINTOUT("%s","read from 'g_serial2'--ttyS2(serial4)!");
				myDelay(RECEIVEDELAY*10);
				memset(g_buf2,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial2,g_buf2,RECVDATA_NUM)==-1)				///read  data from ttyS2
				{
					ERROROUT("read from ttyS2(serial42) failed!");
					tcflush(g_serialFD.st_serial2,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}
#ifndef DEBUG_PC
				if(g_LED.st_mod3>=0)
				{
					#ifdef FREESCALE
						write(g_LED.st_mod3,&setLed_ON,1);
						myDelay(100);
						write(g_LED.st_mod3,&setLed_OFF,1);
					#else
						ioctl(g_LED.st_mod3, SET_LED_ON, NULL);
						myDelay(100);
						ioctl(g_LED.st_mod3, SET_LED_OFF, NULL);
					#endif
				}
#endif
				if(insertRecv(g_buf2)==-1)											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
			if(FD_ISSET(g_serialFD.st_serial3,&l_readset))							///Media electrical device
			{
				PRINTOUT("%s","read from 'g_serial3'--ttyS3(serial6)!");
				myDelay(RECEIVEDELAY);
				memset(g_buf3,0,RECVDATA_NUM);
				if(read(g_serialFD.st_serial3,g_buf3,RECVDATA_NUM)==-1)				///read  data from ttyS3
				{
					ERROROUT("read from ttyS3(serial6) failed!");
					tcflush(g_serialFD.st_serial3,TCIFLUSH);						///flushes data received but not read.
					continue;														///if have error, just ignore, read next.
				}

				if(insertRecv(g_buf3)==-1)											///up direction protocol switch.
				{
					ERROROUT("insertRecv() failed!");
					continue;														///if have error, just ignore.
				}
			}
#endif
		}
	}
}
/***upLoopInit() brief initialize function
 * param	null
 *
 * retval  	0 if successful or -1 if failed.
 ***/
static int upLoopInit()
{
	PRINTOUT("%s","in upLoopInit()");
	return 0;
}
/***insertRecv() brief push struct of receive into receive-list
 * param rec[in],received data to be disposed
 *
 *retval int,0 if successfully or -1 failed.
 ***/
int insertRecv(unsigned char* rec)
{
	char l_tempStr[16];
	int l_sendNum=0;

	if(NULL==rec)			///if receive nothing, just return
		return 0;

	///print received result
#if defined SMARTHOME_DEBUG
	ERROROUT("liuyongfei");
	for(int i=0;i<RECVDATA_NUM;i++)
		
		PRINTOUT("%02x\t",rec[i]);
	PRINTOUT("actual length is : %d \n",strlen((char*)rec));
#endif
	//////smart socket reply//////
	if(rec[0]==0x68 && rec[7]==0x68)
	{
		int l_devPos,l_comPos;
		if(rec[8]==0xc5 && rec[9]==0x03 && rec[14]==0x16 && \
				!(rec[1]==0x20 && rec[2]==0x11 && rec[3]==0x12 && rec[4]==0x06 && rec[5]==0x02))		///control failed, retry
		{
			if(!judgeCheckSum(rec,13))
				return -1;

			if(0xEA==rec[10] || 0xea==rec[10])													///0xEA：感知棒未收到指令返回帧, try again	(不管0xeb)
			{
				sem_wait(&g_devList.st_equip.st_sem);///!!!!!
				l_devPos=findByPoint(&rec[1],find_socketID);
				if(-1==l_devPos)
				{
					sem_post(&g_devList.st_equip.st_sem);///!!!!!
					sprintf(l_tempStr,"%02x%02x%02x%02x%02x%02x#",rec[1],rec[2],rec[3],rec[4],rec[5],rec[6]);
					if(0==strcmp(&g_other.st_shmADDR[CMD_LENGTH_MIN+1],l_tempStr))				///if socket's address validate, retry
					{
						g_other.st_pCmdOther[l_sendNum++]='&';
						g_other.st_pCmdOther[l_sendNum++]='f';
						g_other.st_pCmdOther[l_sendNum++]='2';
						g_other.st_pCmdOther[l_sendNum++]='#';
						g_other.st_pCmdOther[l_sendNum++]='\0';
						///send data to webservice
						sendService(send_only);
						return 0;
					}
					ERROROUT("no this socket!");
					return -1;
				}
				if((rec[11]==0x01 && (0x63==rec[12] || 0x43==rec[12] || 0x93==rec[12])) || (rec[11]==0x04 && (0x55==rec[12] || 0x56==rec[12])))
				{
					PRINTOUT("%s","retry format.");
				}
				else
				{
					ERROROUT("no this retry format!");
					sem_post(&g_devList.st_equip.st_sem);///!!!!!
					return -1;
				}
				unsigned char l_cmdType,l_param0,l_param1;
				if(0x01==rec[11])			///inquiry kind
					l_cmdType=0x02;
				else if(0x04==rec[11])		///control kind
					l_cmdType=0x01;
				if(0x63==rec[12])			///power
				{
					l_param0=0x02;l_param1=0x01;
				}
				else if(0x43==rec[12])		///total-power
				{
					l_param0=0xfd;l_param1=0x01;
				}
				else if(0x93==rec[12])		///status through socket
				{
					l_param0=0xfc;l_param1=0x01;
				}
				else if(0x55==rec[12])		///socket-off
				{
					l_param0=0x01;l_param1=0x00;
				}
				else if(0x56==rec[12])		///socket-on
				{
					l_param0=0x01;l_param1=0x01;
				}

				sem_wait(&g_downTask.st_task.st_sem);///!!!!!
				int i;
				for(i=g_downTask.st_task.head;i!=NO_MORE;i=g_downTask.st_command[i].next)
				{
					if(prio_retry==g_downTask.st_command[i].priority && com_havRetry==g_downTask.st_command[i].needRetry && \
							l_cmdType==g_downTask.st_command[i].cmdType && l_param0==g_downTask.st_command[i].param[0] && \
							l_param1==g_downTask.st_command[i].param[1] && g_downTask.st_command[i].typeID[0]==(g_devList.st_equipArray[l_devPos].typeID>>16 & 0xff) \
							&& g_downTask.st_command[i].typeID[1]==(g_devList.st_equipArray[l_devPos].typeID>>8 & 0xff) \
							&& g_downTask.st_command[i].typeID[2]==(g_devList.st_equipArray[l_devPos].typeID & 0xff))
						break;
				}
				if(i!=NO_MORE)
				{
					if(g_downTask.st_command[i].retryTime >= RETRY_NUM )
					{
						PRINTOUT("%s","don't retry forever!");
						removeElem(g_downTask.st_task,i);
					}
					else
					{
						PRINTOUT("%s","try again!");
						g_downTask.st_command[i].needRetry=com_waitRetry;
						g_downTask.st_command[i].removeNum=0;
					}
					sem_post(&g_downTask.st_task.st_sem);///!!!!!
					sem_post(&g_devList.st_equip.st_sem);///!!!!!
					return 0;
				}
				sem_post(&g_downTask.st_task.st_sem);///!!!!!

				sem_wait(&g_downTask.st_emtpy.st_sem);///!!!!!
				l_comPos=getElem(g_downTask.st_emtpy);
				sem_post(&g_downTask.st_emtpy.st_sem);///!!!!!
				if(-1==l_comPos)
				{
					ERROROUT("no enough command struct!");
					sem_post(&g_devList.st_equip.st_sem);///!!!!!
					return -1;
				}
				g_downTask.st_command[l_comPos].typeID[0]=g_devList.st_equipArray[l_devPos].typeID>>16 & 0xff;
				g_downTask.st_command[l_comPos].typeID[1]=g_devList.st_equipArray[l_devPos].typeID>>8 & 0xff;
				g_downTask.st_command[l_comPos].typeID[2]=g_devList.st_equipArray[l_devPos].typeID & 0xff;
				sem_post(&g_devList.st_equip.st_sem);///!!!!!

				g_downTask.st_command[l_comPos].cmdType=l_cmdType;
				g_downTask.st_command[l_comPos].param[0]=l_param0;
				g_downTask.st_command[l_comPos].param[1]=l_param1;
				g_downTask.st_command[l_comPos].priority=prio_retry;
				g_downTask.st_command[l_comPos].otherParam=0;
				g_downTask.st_command[l_comPos].retryTime=1;
				g_downTask.st_command[l_comPos].needRetry=com_waitRetry;
				g_downTask.st_command[l_comPos].removeNum=0;

				sem_wait(&g_downTask.st_task.st_sem);///!!!!!
				insertElem(g_downTask.st_task,l_comPos);
				sem_post(&g_downTask.st_task.st_sem);///!!!!!
#if defined SMARTHOME_DEBUG
				saveComInDatabase(rec,15,false);///68 a0 a1 a2 a3 a4 a5 68 C5 01 xx xx xx cs 16
#endif
			}
			else
			{
				ERROROUT("no support retry error!");
				return -1;
			}
		}
		/* 2012-03-10 V1.0.5 modify by LiuHaifeng begin */
		///validate return
		else if (rec[8]==0x84 && rec[9]==0x02 && rec[10]==0xe4 && rec[11]==0x35 && rec[13]==0x16)
		{
			if(!judgeCheckSum(rec,12))
				return -1;
			sprintf(l_tempStr,"%02x",rec[11]-0x35);
			g_other.st_pCmdOther[l_sendNum++]='&';
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
			g_other.st_pCmdOther[l_sendNum++]='#';
			g_other.st_pCmdOther[l_sendNum++]='\0';
			///send data to webservice
			sendService(send_only);
		}
		///on return
		else if (rec[8]==0x84 && rec[9]==0x02 && rec[10]==0xe4 && rec[11]==0x33 && rec[13]==0x16)
		{
			if(!judgeCheckSum(rec,12))
				return -1;
			sprintf(l_tempStr,"%02x",rec[11]-0x33);
			g_other.st_pCmdOther[l_sendNum++]='&';
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
			g_other.st_pCmdOther[l_sendNum++]='#';
			g_other.st_pCmdOther[l_sendNum++]='\0';
			///send data to webservice
			sendService(send_only);
		}
		///off return
		else if (rec[8]==0x84 && rec[9]==0x02 && rec[10]==0xe5 && rec[11]==0x34 && rec[13]==0x16)
		{
			if(!judgeCheckSum(rec,12))
				return -1;
			sprintf(l_tempStr,"%02x",rec[11]-0x34);
			g_other.st_pCmdOther[l_sendNum++]='&';
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
			g_other.st_pCmdOther[l_sendNum++]='#';
			g_other.st_pCmdOther[l_sendNum++]='\0';
			///send data to webservice
			sendService(send_only);
		}
		/* 2012-03-10 V1.0.5 modify by LiuHaifeng end */
		else if(rec[8]==0x84 && rec[9]==0x02 && rec[10]==0xe3 && rec[13]==0x16)					///curtain control reply
		{
			if(!judgeCheckSum(rec,12))
				return -1;

			if('8'!=g_other.st_shmADDR[2] && '6'==g_other.st_shmADDR[5] && '1'==g_other.st_shmADDR[14])		///if curtain
			{
				g_other.st_pCmdOther[l_sendNum++]='&';
				g_other.st_pCmdOther[l_sendNum++]='0';
				if(0x33==rec[11])
				{
					g_other.st_pCmdOther[l_sendNum++]='1';		///forward
				}
				else if(0x34==rec[11])
				{
					g_other.st_pCmdOther[l_sendNum++]='2';		///back
				}
				else if(0x35==rec[11])
				{
					g_other.st_pCmdOther[l_sendNum++]='0';		///stop
				}
				g_other.st_pCmdOther[l_sendNum++]='#';
				g_other.st_pCmdOther[l_sendNum++]='\0';
				///send data to webservice
				sendService(send_only);
			}
			else
			{
				ERROROUT("no relative return!");
				return -1;
			}

#if defined SMARTHOME_DEBUG
			saveComInDatabase(rec,14,false);///68 a0 a1 a2 a3 a4 a5 68 84 02 88 XX cs 16
#endif
		}
		else if(rec[8]==0x84 && rec[9]==0x02 && rec[10]==0x88 && rec[13]==0x16)					///socket off control reply
		{
			if(!judgeCheckSum(rec,12))
				return -1;

			sem_wait(&g_devList.st_equip.st_sem);///!!!!!
			l_devPos=findByPoint(&rec[1],find_socketID);
			if(-1==l_devPos)
			{
				ERROROUT("no this socket!");
				sem_post(&g_devList.st_equip.st_sem);///!!!!!
				return -1;
			}
			///update 'g_devList.st_equipArray[i].socketStatus'
			g_devList.st_equipArray[l_devPos].socketStatus=rec[11]-0x33-0x55;
			sem_post(&g_devList.st_equip.st_sem);///!!!!!
			///see need send to web-service
			#if 1
			if('8'!=g_other.st_shmADDR[2] && '1'==g_other.st_shmADDR[14] && '1'==g_other.st_shmADDR[17] && '0'==g_other.st_shmADDR[19])
			{
				sprintf(l_tempStr,"%02x",rec[11]-0x33-0x55);
				g_other.st_pCmdOther[l_sendNum++]='&';
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
				g_other.st_pCmdOther[l_sendNum++]='#';
				g_other.st_pCmdOther[l_sendNum++]='\0';
				///send data to webservice
				sendService(send_only);
				PRINTOUT("%s","send web off right");
			}
			else
			{
				struct timeval l_tv;
				if(gettimeofday(&l_tv,NULL)==-1)
				{
					ERROROUT("get-time failed!");
				}
				optTimes++;
				optBegin_time=l_tv.tv_sec;
			}
			#endif
#if defined SMARTHOME_DEBUG
			saveComInDatabase(rec,14,false);///68 a0 a1 a2 a3 a4 a5 68 84 02 88 XX cs 16
#endif
			return 0;
		}
		else if(rec[8]==0x84 && rec[9]==0x02 && rec[10]==0x89 && rec[13]==0x16)					///socket on control reply
		{
			if(!judgeCheckSum(rec,12))
				return -1;

			sem_wait(&g_devList.st_equip.st_sem);///!!!!!
			l_devPos=findByPoint(&rec[1],find_socketID);
			if(-1==l_devPos)
			{
				ERROROUT("no this socket!");
				sem_post(&g_devList.st_equip.st_sem);///!!!!!
				return -1;
			}
			///update 'g_devList.st_equipArray[i].socketStatus'
			g_devList.st_equipArray[l_devPos].socketStatus=rec[11]-0x33-0x55;
			sem_post(&g_devList.st_equip.st_sem);///!!!!!
			///see need send to web-service
			if('8'!=g_other.st_shmADDR[2] && '1'==g_other.st_shmADDR[14] && '1'==g_other.st_shmADDR[17] && '1'==g_other.st_shmADDR[19])
			{
				sprintf(l_tempStr,"%02x",rec[11]-0x33-0x55);
				g_other.st_pCmdOther[l_sendNum++]='&';
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
				g_other.st_pCmdOther[l_sendNum++]='#';
				g_other.st_pCmdOther[l_sendNum++]='\0';
				///send data to webservice
				sendService(send_only);
			}
			else
			{
				struct timeval l_tv;
				if(gettimeofday(&l_tv,NULL)==-1)
				{
					ERROROUT("get-time failed!");
				}
				optTimes++;
				optBegin_time=l_tv.tv_sec;
			}

#if defined SMARTHOME_DEBUG
			saveComInDatabase(rec,14,false);///68 a0 a1 a2 a3 a4 a5 68 84 02 89 XX cs 16
#endif
			return 0;
		}
		else if(rec[8]==0x81 && rec[9]==0x03 && rec[10]==0x93 && rec[11]==0xe9 && rec[14]==0x16)///socket status reply--状态返回
		{
			if(!judgeCheckSum(rec,13))
				return -1;

			sem_wait(&g_devList.st_equip.st_sem);///!!!!!
			l_devPos=findByPoint(&rec[1],find_socketID);
			if(-1==l_devPos)
			{
				sem_post(&g_devList.st_equip.st_sem);///!!!!!
				sprintf(l_tempStr,"%02x%02x%02x%02x%02x%02x#",rec[1],rec[2],rec[3],rec[4],rec[5],rec[6]);
				if(0==strcmp(&g_other.st_shmADDR[CMD_LENGTH_MIN+1],l_tempStr))
				{
					g_other.st_pCmdOther[l_sendNum++]='&';
					g_other.st_pCmdOther[l_sendNum++]='0';
					g_other.st_pCmdOther[l_sendNum++]='0';
					g_other.st_pCmdOther[l_sendNum++]='#';
					g_other.st_pCmdOther[l_sendNum++]='\0';
					///send data to webservice
					sendService(send_only);
					return 0;
				}
				ERROROUT("no this socket!");
				return -1;
			}
			///update 'g_devList.st_equipArray[i].socketStatus'
			g_devList.st_equipArray[l_devPos].socketStatus=rec[12]-0x33-0x55;
			sem_post(&g_devList.st_equip.st_sem);///!!!!!

#if defined SMARTHOME_DEBUG
			saveComInDatabase(rec,15,false);///68 a0 a1 a2 a3 a4 a5 68 81 03 93 e9 XX cs 16
#endif
			return 0;
		}
		else if(rec[8]==0x81 && rec[9]==0x05 && rec[10]==0x63 && rec[11]==0xe9 && rec[16]==0x16)///active power--有功功率
		{
			if(!judgeCheckSum(rec,15))
				return -1;

			sem_wait(&g_devList.st_equip.st_sem);///!!!!!
			l_devPos=findByPoint(&rec[1],find_socketID);
			if(-1==l_devPos)
			{
				sem_post(&g_devList.st_equip.st_sem);///!!!!!
				sprintf(l_tempStr,"%02x%02x%02x%02x%02x%02x#",rec[1],rec[2],rec[3],rec[4],rec[5],rec[6]);
				if(0==strcmp(&g_other.st_shmADDR[CMD_LENGTH_MIN+1],l_tempStr))
				{
					double l_data=bcdChange(rec[14]-0x33)+ 0.01*bcdChange(rec[13]-0x33)+0.0001*bcdChange(rec[12]-0x33);
					g_other.st_pCmdOther[l_sendNum++]='&';
					sprintf(l_tempStr,"%08f",l_data);
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[2];
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[3];
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[4];
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[5];
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[6];
					g_other.st_pCmdOther[l_sendNum++]=l_tempStr[7];
					g_other.st_pCmdOther[l_sendNum++]='#';
					g_other.st_pCmdOther[l_sendNum++]='\0';
					///send data to webservice
					sendService(send_only);
					return 0;
				}
				ERROROUT("no this socket!");
				return -1;
			}
			double l_data=bcdChange(rec[14]-0x33)+ 0.01*bcdChange(rec[13]-0x33)+0.0001*bcdChange(rec[12]-0x33);
			///send to webservice
			if((isSet() || inDispose()) && '2'==g_other.st_shmADDR[14] && '2'==g_other.st_shmADDR[17] && '1'==g_other.st_shmADDR[19])
			{
				g_other.st_pCmdOther[l_sendNum++]='&';
				sprintf(l_tempStr,"%08f",l_data);
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[2];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[3];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[4];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[5];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[6];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[7];
				g_other.st_pCmdOther[l_sendNum++]='#';
				g_other.st_pCmdOther[l_sendNum++]='\0';
				///send data to webservice
				sendService(send_only);
			}
			else
			{
				if(-1==saveActivePower(l_devPos,l_data))
				{
					ERROROUT("save active power failed!");
					sem_post(&g_devList.st_equip.st_sem);///!!!!!
					return -1;
				}
			}
			sem_post(&g_devList.st_equip.st_sem);///!!!!!
#if defined SMARTHOME_DEBUG
			saveComInDatabase(rec,17,false);///68-a0 a1 a2 a3 a4 a5-68 81 05 63 E9 xx xx xx cs 16
#endif
		}
		else if(rec[8]==0x81 && rec[9]==0x06 && rec[10]==0x43 && rec[11]==0xc3 && rec[17]==0x16)///total elec power--电量
		{
			if(!judgeCheckSum(rec,16))
				return -1;

			sem_wait(&g_devList.st_equip.st_sem);///!!!!!
			l_devPos=findByPoint(&rec[1],find_socketID);
			if(-1==l_devPos)
			{
				ERROROUT("no this socket!");
				sem_post(&g_devList.st_equip.st_sem);///!!!!!
				return -1;
			}
			double l_data=bcdChange(rec[12]-0x33)*0.01+bcdChange(rec[13]-0x33)+bcdChange(rec[14]-0x33)*100;
			if(-1==saveElecPower(l_devPos,l_data))
			{
				ERROROUT("save elec-power failed!");
				sem_post(&g_devList.st_equip.st_sem);///!!!!!
				return -1;
			}
			sem_post(&g_devList.st_equip.st_sem);///!!!!!

#if defined SMARTHOME_DEBUG
			saveComInDatabase(rec,18,false);///68 a0 a1 a2 a3 a4 a5 68 81 06 43 C3 xx xx xx xx cs 16
#endif
		}
		else if((rec[8]==0x8d || rec[8]==0x8D) && rec[9]==0x06 && rec[17]==0x16)				///lightcontrol bind return
		{
			if((rec[1]==((rec[10]-0x33+0x100)&0xff)) && (rec[2]==((rec[11]-0x33+0x100)&0xff)) && (rec[3]==((rec[12]-0x33+0x100)&0xff)) && (rec[4]==((rec[13]-0x33+0x100)&0xff)) && (rec[5]==((rec[14]-0x33+0x100)&0xff)) && (rec[6]==((rec[15]-0x33+0x100)&0xff)))
			{
				sprintf(l_tempStr,"%02x%02x%02x%02x%02x%02x",rec[1],rec[2],rec[3],rec[4],rec[5],rec[6]);
				if(g_other.st_shmADDR[14]=='2' && g_other.st_shmADDR[17]=='7' && g_other.st_shmADDR[19]=='1')
				{
					g_other.st_pCmdOther[0]=l_tempStr[0];g_other.st_pCmdOther[1]=l_tempStr[1];g_other.st_pCmdOther[2]=l_tempStr[2];
					g_other.st_pCmdOther[3]=l_tempStr[3];g_other.st_pCmdOther[4]=l_tempStr[4];g_other.st_pCmdOther[5]=l_tempStr[5];
					g_other.st_pCmdOther[6]=l_tempStr[6];g_other.st_pCmdOther[7]=l_tempStr[7];g_other.st_pCmdOther[8]=l_tempStr[8];
					g_other.st_pCmdOther[9]=l_tempStr[9];g_other.st_pCmdOther[10]=l_tempStr[10];g_other.st_pCmdOther[11]=l_tempStr[11];
					g_other.st_pCmdOther[12]='#';
					g_other.st_pCmdOther[13]='\0';
					///send data to webservice
					sendService(send_only);
				}
			}

#if defined SMARTHOME_DEBUG
			saveComInDatabase(rec,18,false);///68 xx xx xx xx xx xx 68 8D 06 33 33 33 33 33 33 95 16
#endif
		}
		else
		{
			ERROROUT("the format of data received no support!");
			return -1;
		}
	}
	//////Media reply//////
	else if(rec[0]==0x09 && rec[4]==0x34 && rec[5]==0x12)
	{
		if('8'==g_other.st_shmADDR[2] && '2'==g_other.st_shmADDR[3] && '1'==g_other.st_shmADDR[14] && rec[1]==0x04 )   ///control replay
		{
				g_other.st_pCmdOther[l_sendNum++]='&';
				sprintf(l_tempStr,"%02x",rec[8]);
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
				g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
				g_other.st_pCmdOther[l_sendNum++]='#';
				g_other.st_pCmdOther[l_sendNum++]='\0';
				///send data to webservice
				sendService(send_only);
		}
		else if('8'==g_other.st_shmADDR[2] && '2'==g_other.st_shmADDR[3] && ('2'==g_other.st_shmADDR[14] || '4'==g_other.st_shmADDR[14]) && rec[1]==0xf1 )   ///query operID replay
		{
			g_other.st_pCmdOther[l_sendNum++]='&';
			sprintf(l_tempStr,"%02x",rec[3]);
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
			sprintf(l_tempStr,"%02x",rec[2]);
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
			g_other.st_pCmdOther[l_sendNum++]='#';
			g_other.st_pCmdOther[l_sendNum++]='\0';
			///send data to webservice
			sendService(send_only);
		}
#if defined SMARTHOME_DEBUG
		saveComInDatabase(rec,9,false);///09-04-0f00-3412-0000-00
#endif
	}

	else if(rec[0]==0x0b && rec[1]==0x06 && rec[4]==0x34 && rec[5]==0x12 && rec[8]==0x01)
	{
		if('8'==g_other.st_shmADDR[2] && '2'==g_other.st_shmADDR[3] && '2'==g_other.st_shmADDR[14] && '6'==g_other.st_shmADDR[17] && '3'==g_other.st_shmADDR[19] )   ///query
		{
			g_other.st_pCmdOther[l_sendNum++]='&';
			sprintf(l_tempStr,"%02x",rec[9]);
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
			sprintf(l_tempStr,"%02x",rec[10]);
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[0];
			g_other.st_pCmdOther[l_sendNum++]=l_tempStr[1];
			g_other.st_pCmdOther[l_sendNum++]='#';
			g_other.st_pCmdOther[l_sendNum++]='\0';
			///send data to webservice
			sendService(send_only);
		}

#if defined SMARTHOME_DEBUG
		saveComInDatabase(rec,11,false);///0b-06-0f00-3412-0000-01-03-0x
#endif
	}
	//////safeguard reply//////
#ifdef DEBUG_PC
	else
#elif defined DEBUG_SOCKET
	else
#elif defined DEBUG_ARM
	else if((&rec[0] == &g_buf2[0]) || (&rec[0] == &g_buf3[0]))
#endif
	{
		struct timeval l_tv;
		int l_temp=0;
		int l_recvPos;

		sem_wait(&g_upTask.st_emtpy.st_sem);///!!!!!
		l_recvPos=getElem(g_upTask.st_emtpy);
		sem_post(&g_upTask.st_emtpy.st_sem);///!!!!!
		///alarm info full
		if(-1==l_recvPos)
		{
			ERROROUT("alarm info full!");
			int l_head;
			int l_tmptime=0;
			int l_tmpNUM=-1;
			sem_wait(&(g_upTask.st_safeguardList.st_sem));///!!!!!
	    	l_head=g_upTask.st_safeguardList.head;
			if(gettimeofday(&l_tv,NULL)==-1)
			{
				ERROROUT("get-time failed!");
			}
	    	while(l_head!=NO_MORE)
	    	{
	    		if (g_upTask.st_recvData[l_head].data.safeGuard.sendFlag==false)
	    		{
	    			if((l_tv.tv_sec-g_upTask.st_recvData[l_head].data.safeGuard.time)>l_tmptime)
	    			{
	    				l_tmptime=l_tv.tv_sec-g_upTask.st_recvData[l_head].data.safeGuard.time;
	    				l_tmpNUM=l_head;
	    			}
	    		}
	    		l_head=g_upTask.st_recvData[l_head].next;
	    	}
			if(l_tmpNUM==NO_MORE)
			{
				sem_post(&(g_upTask.st_safeguardList.st_sem));///!!!!!
				return 0;
			}
			else
			{
				sem_wait(&(g_upTask.st_emtpy.st_sem));///!!!!!
				if(-1==removeElem(g_upTask.st_safeguardList,l_tmpNUM))
				{
					ERROROUT("delete device from memory failed!");
				}
				ERROROUT("delete last alarm info success!");
				sem_post(&(g_upTask.st_emtpy.st_sem));///!!!!!
			}
			sem_post(&(g_upTask.st_safeguardList.st_sem));///!!!!!
			sem_wait(&g_upTask.st_emtpy.st_sem);///!!!!!
			l_recvPos=getElem(g_upTask.st_emtpy);
			sem_post(&g_upTask.st_emtpy.st_sem);///!!!!!
		}
		///add alarm
		if(gettimeofday(&l_tv,NULL)==-1)
		{
			ERROROUT("get-time failed!");
		}
		sem_wait(&g_upTask.st_safeguardList.st_sem);///!!!!!
		for (int i=g_upTask.st_safeguardList.head;i!=NO_MORE;i=g_upTask.st_recvData[i].next)
		{
			int l_count=0;
			for(int j=0;j<RECVDATA_NUM;j++)
			{
				if (g_upTask.st_recvData[i].data.safeGuard.safeguardAddr[j]==rec[j])
					l_count++;
			}
			if (l_count==RECVDATA_NUM)
		    {
				if((l_tv.tv_sec-g_upTask.st_recvData[i].data.safeGuard.time)<ALARMTIME)
				{
					sem_post(&g_upTask.st_safeguardList.st_sem);///!!!!!
					sem_wait(&g_upTask.st_emtpy.st_sem);///!!!!!
					insertElem(g_upTask.st_emtpy,l_recvPos);
					sem_post(&g_upTask.st_emtpy.st_sem);///!!!!!
					return 0;
				}
				else
					break;
		    }
		}
		for (int i=0;i<RECVDATA_NUM;i++)
		{
			g_upTask.st_recvData[l_recvPos].data.safeGuard.safeguardAddr[i]=rec[l_temp];
			l_temp++;
		}
		g_upTask.st_recvData[l_recvPos].data.safeGuard.time=l_tv.tv_sec;
		g_upTask.st_recvData[l_recvPos].data.safeGuard.sendFlag=true;
		///insert
		insertElem(g_upTask.st_safeguardList,l_recvPos);
		sem_post(&g_upTask.st_safeguardList.st_sem);///!!!!!

#if defined SMARTHOME_DEBUG
		saveComInDatabase(g_upTask.st_recvData[l_recvPos].data.safeGuard.safeguardAddr,RECVDATA_NUM,false);///aa-bb-cc-dd
#endif
	}
	return 0;
}
/***bcdChange() brief change BCD to int.
 *param input[in], the data will be switch.
 *retval int, -1 if failed or changed result successful.
 ***/
int bcdChange(unsigned char input)
{
	return ((input>>4)*10+(input&0x0f));
}
